/**********************************************************************
 * Ajax Tools
 * For fxLiimova project.
 *
 * zh_CN.UTF-8
 * Fiathux Su
 * Copyright 2008-2010
 **********************************************************************/


/* -----------------------------------------------------------------------------
 * Ajax Base
 * Basic AJAX implementation it is using XMLHttpRequest to request data from web
 * server. When success, there back a text data or a HTML DOM object. 
 -------------------------------------------------------------------------------*/
var Ajax_base=function(){
    var me=this;
    var http_req=null;
    var req_type=0;//Back type. 0 for text, 1 for dom, 2 for object
    var req_class="";//If req_type set 2 specify object class name
    //event
    me.onerror=null;//Event on error occurting
    me.onload=null;//Event data loaded
    //property
    me.method="POST";//Specify HTTP request method. Now support 'POST' and 'GET'
    me.src="";//Request address URL
    me.parameter=new Array();//(NW)Some parameter that send to HTTP server program
    me.error=null;//(NW)Last error information.
    me.result=null;//Data result
    me.readystate=0;//XMLHttpRequest readystate
    //method
    /* me.addparam(name,value)  Add for send a parameter
     * me.cleanparam()          Clean all send parameter 
     * me.reqtext()             Request data from server and back a text string
     * me.reqdom()              Request data from server and back a DOM object
     * me.reqobj(tag)           Back data by specify object
     */

    //Initialization XMLHttpRequest
    if (window.XMLHttpRequest){
        http_req=new XMLHttpRequest;//Mozilla & IE7 or up
    }else if (window.ActiveXObject){//IE5 & IE6
        try{
            http_req=new ActiveXObject("Msxml2.XMLHTTP");//msxml3.dll+
        }catch(error_tmp0){
            try{
                http_req=new ActiveXObject("Microsoft.XMLHTTP");//msxml2.6-
            }catch(error_tmp1){
                me.error=new Ajax_error("def_obj");//failed
                return;
            }
        }
    }else{
        me.error=new Ajax_error("def_obj");
        return;
    }

    //HTTP callback
    http_req.onreadystatechange=function(){
        var http_status;
        me.readystate=http_req.readyState;
        /* ------------
         * readystate reference from the W3C document:
         * 0 Uninitialized
         * 1 Loading
         * 2 Loaded
         * 3 Interactive
         * 4 Completed
         * 
         * http://www.w3.org/TR/XMLHttpRequest
         */
        if (me.readystate<=3)return;//Not completed
        if (me.readystate==4){//Completed
            http_status=http_req.status;//The status code reference RFC2616
            if (http_status==200){//code 200 success
                if (req_type>0){//Convert XML text to XML DOM
                    var dom_obj=null;
                    try{//For Mozilla
					    dom_obj=(new DOMParser()).parseFromString(http_req.responseText,"text/xml");
				    }catch(error_tmp0){
					    try{//For IE
					        dom_obj=new ActiveXObject ("MSXML2.DOMDocument");
					        dom_obj.loadXML(http_req.responseText);
					    }catch(error_tmp1){
                            me.error=new Ajax_error("convert_dom");
						    if(me.onerror)me.onerror(error_tmp1.description);//XML convert error
                            me.result=null;
					    }
				    }
                    if (dom_obj)
                        if (!xmlpack(dom_obj))return;//If pack error
                }else{//Back text data
                    me.result=http_req.responseText;
                }
                if (me.onload)me.onload();
            }else if(me.onerror){//HTTP get an error code
                me.error=new Ajax_error("http_status");
                me.onerror(http_status);
            }
        }
    }

    //Pack XML data to a object
    var xmlpack(dom_obj){
        switch (req_type){
        case 1://DOM object
            me.result=dom_obj;
            break;
        case 2://Custom object
            //{todo: some custom object convert method}
            break;
        default:
            alert("code error:call xmlpack()");
        }
    }

    //Add parameter
    var addparam(name,value){
        me.parameter[me.parameter.length]=new function(){
            this.name=name;//get the Closure 'name'
            this.value=value;//get the Closure 'value'
        }
    }

    //clean parameter
    var cleanparam(){
        me.parameter=new Array();
    }
    
    //
}

/* -----------------------------------------------------------------------------
 * Ajax error
 * An error object it include a hint text table
 -------------------------------------------------------------------------------*/
var Ajax_error=function(errorcode){
    this.code=errorcode;
    switch(this.code){
        case "def_obj":
            this.inf="无法创建网络访问对象XMLHttpRequest";
            this.type="not_support";
            break;
        case "convert_dom":
            this.inf="无法创建DOM对象";
            this.type="not_support";
            break;
        case "http_status":
            this.inf="无法从服务器获取数据";
            this.type="server_error";
            break;
        default:
            this.inf="未知错误";
            this.type="unknow";
    }
}

///////////////////////////////////////////////////////////////////////////////
var Ajax_support=function(){
    var http_req=null;
    var me=this;
    var http_state=0;
    var http_status=0;
    //属性
    me.error=null;//错误值
    me.objxml=false;//是否返回XML对象，否则返回文本
    me.context=null;//返回数据
    //事件
    me.onsuccess=false;//请求成功
    me.onerror=false;//请求失败
    //初始化
    if (window.XMLHttpRequest){
        http_req=new XMLHttpRequest;//Mozilla和IE7以上浏览器
    }else if (window.ActiveXObject){//IE5和IE6
        try{
            http_req=new ActiveXObject("Msxml2.XMLHTTP");//msxml3.dll+
        }catch(error_tmp0){
            try{
                http_req=new ActiveXObject("Microsoft.XMLHTTP");//msxml2.6-
            }catch(error_tmp1){
                me.error="无法创建HTTP请求支持，请检查msxml3.dll以及您的浏览器设置。";//失败
                return null;
            }
        }
    }else{
        me.error="无法创建HTTP请求支持，您的浏览器不支持或禁用了此功能。";
        return null;
    }
    http_req.onreadystatechange=function(){//HTTP请求回调
        var http_stat;
        http_state=http_req.readyState;
        if (http_state<=3)return 0;//正在进行数据请求
        if (http_state==4){
            http_status=http_req.status;
            if (http_status==200){//请求成功
                if (me.objxml){//转换XML文本为XMLDOM对象
                    try{//非IE浏览器
					me.context=(new DOMParser()).parseFromString(http_req.responseText,"text/xml");
				}catch(error_tmp0){
					try{//IE浏览器
						me.context=new ActiveXObject ("MSXML2.DOMDocument");
						me.context.loadXML(http_req.responseText);
					}catch(error_tmp1){
                              me.error=error_tmp1.description;
						if(me.onerror)me.onerror(error_tmp1.description);//XML解析失败
                              me.context=null;
					}
				}
                }else{
                    me.context=http_req.responseText;
                }
                if (me.onsuccess)me.onsuccess(me.context);
            }else if(me.onerror){//请求失败
                me.error="";
                me.error="数据请求发生错误，HTTP错误代码：" + http_status;
                me.onerror(me.error);
            }
        }
    }
    //过程
    me.readycode=function(){//返回HTTP请求准备代码
        return http_state;
    }

    me.statuscode=function(){//返回HTTP请求状态代码
        return http_status;
    }

    me.postsend=function(url,data){//以Post模式发送请求
        try{
            http_req.open("POST",url,true);
            //指定HTTP头以便发出Post数据
            http_req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            if (data)http_req.setRequestHeader("Content-length", data.length);
            http_req.setRequestHeader("Connection", "close");
            if (!data)http_req.send(null);
            else{
                http_req.send(data);
            }
        }
        catch (error_tmp0){
            me.error=error_tmp0.description;
            return false;
        }
        return true;
    }    

    me.getsend=function(url){//以Get模式发送请求
        try{
            http_req.open("GET",url,true);
            http_req.send(null);
        }
        catch (error_tmp0){
            me.error=error_tmp0.description;
            return false;
        }
        return true;
    }

    me.dataencode=function(data){//对发送的数据结构进行URI编码
        /* NOTE:
         * data=array(object{name,value}...)
         */
        var elem;
        var uristr="";
        try{
            for (elem in data){//枚举数据单元
                if (uristr!="")uristr+="&";
                uristr+=encodeURIComponent(elem.name);
                uristr+="=";
                uristr+=encodeURIComponent(elem.value);
            }
        }catch(error_tmp0){
            return "";
        }
        return uristr;
    }
}

var Ajax_object=function(){
    var asx=new Ajax_support();
    var me=this;
}
/* -----------------------------------------------------------------------------
 * Ajax_text 2.0
 * 提供一种简单的无刷新后台数据请求方式，返回数据主要以text方式或者XML DOM方式返
 * 回，程序不作任何额外的解析，仅仅提供一个简化的方法。该模块与1.0版本不兼容，但
 * 是运行思想基本一致，可以通过小规模的代码修改实现移植。
 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 * API
 * --------------------
 * 属性：
 * error    记录最后一次出错的详情，默认为null
 * method   发送参数的方式，可选'GET'和'POST'，默认为'GET'
 * url      访问信息的URL地址
 * app      解析服务器返回数据的方式，可选'text'和'xmldom'，默认为'text'
 * 
 * 事件：
 * ondata   数据请求成功时的回调函数，函数原型为"function ondata(svrback){}"，其
 *          中Svrback参数为服务器返回的数据
 * onerror  请求数据发生错误时的回调函数，函数原型为"function onerror(errinf){}"，
 *          其中errinf参数为错误信息详情，此参数触发时errinf的数据和error属性的
 *          值相同
 * 
 * 方法：
 * req()    发起数据请求，请求成功返回true，否则返回false
 * postsend_add(name,value)     添加发起POST访问时传递的参数，name为参数名称，
 *                              value为参数值，所有参数类型均为字符串。
 * postsend_clear()     清空之前所有定义的POST参数。
 -------------------------------------------------------------------------------*/
var Ajax_text=function(){
    var asx=new Ajax_support();//载入基础库
    if (asx.error){//基础库载入失败
        me.error=asx.error;
        return;
    }
    var me=this;
    var pram=new Array();//请求的POST参数
    //属性
    me.error=null;//返回错误信息
    me.method="GET";//发送数据方式
    me.url="";//URL指向
    me.app="text";//应用解析方式
    //事件
    me.ondata=null;//数据成功返回
    me.onerror=null;//访问或应用发生错误

    asx.onsucccess=function(dat){//请求成功
        if (me.ondata)me.ondata(dat);
    }

    asx.onerror=function(err){//请求失败
        me.error=asx.error;
        if (me.onerror)me.onerror(err);
    }

    me.req=function(){//发出请求
        if (!(/^.+$/.test(me.url))){
            me.error="URI定位不合法，它不能包含换行符，不能为空";
            return false;
        }
        switch(me.app.toLowerCase()){//检查应用方式
        case "text"://纯文本
            asx.objxml=false;break;
        case "xmldom"://XMLDOM
            asx.objxml=true;break;
        default:
            me.error="asx.app未知的信息应用方式："+me.app;
            return false;
        }
        switch(me.method.toUpperCase()){//根据指定的方式发起请求
        case "GET"://GET方式
            if (!asx.getsend(me.url)){
                me.error=asx.error;
                return false;
            }
            break;
        case "POST"://POST方式
            var tmpparm;
            tmpparm=(pram.length<=0)?null|asx.dataencode(pram);
            if (!asx.postsend(me.url,tmpparm)){
                me.error=asx.error;
                return false;
            }
            break;
        default://
            me.error="asx.method未知的请求方法："+me.method;
            return false;
        }
        return true;
    }

    me.postsend_add=function(name,value){//添加Post传递参数
        pram[pram.length]=new function(){
            this.name=name;
            this.value=value;
        }
    }

    me.postsend_clear=function(){//清空Post传递参数
        pram=new Array();
    }
}
